#include <stdlib.h>
#include <stdint.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "IdGenerator.h"
#include "IdGenOptions.h"
#include "YitIdHelper.h"

/**
 * 获取table key对应的value
 * 
*/
static int getfield(lua_State *L, const char *key, int* result) {
    lua_pushstring(L, key);
    lua_gettable(L, -2);  
    if (lua_isnil(L, -1))
    {
        lua_pop(L, 1);
        return -1;
    }
    if (!lua_isnumber(L, -1))
        luaL_error(L, "invalid component in idgen option!");
    *result = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);
    return 0;
}

/**
 * 设置IdGenerator的参数
 * @function idgen.set_option
 * @param option 
 * 默认值
 * {
 *      method = 1,
 *      baseTime = 1582136402000, //2020年
 *      workerId = 1, //必须设置
 *      workerIdBitlength = 6,
 *      seqBitlength = 6,
 *      maxSeqNumber = 0,
 *      minSeqNumber = 5,
 *      topOverCostCount = 2000,
 * }
 * @return
 */
static int
lsetOption(lua_State *L) {
    if (!lua_istable(L,-1)) {
        luaL_error(L, "set_option need a table arg!");
        return 0;
    }
    int value = 0;
    if (!(getfield(L, "workerId", &value) == 0)) {
        luaL_error(L, "workerId is required in function set_option");
        return 0;
    }
    IdGeneratorOptions options = BuildIdGenOptions((uint32_t)value);
    if (getfield(L, "method", &value) == 0) {
        options.Method = (uint8_t)value;
    }
    if (getfield(L, "baseTime", &value) == 0) {
        options.BaseTime = (uint64_t)value;
    }
    if (getfield(L, "workIdBitlength", &value) == 0) {
        options.WorkerIdBitLength = (uint8_t)value;
    }
    if (getfield(L, "seqBitlength", &value) == 0) {
        options.SeqBitLength = (uint8_t)value;
    }
    if (getfield(L, "maxSeqNumber", &value) == 0) {
        options.MaxSeqNumber = (uint32_t)value;
    }
    if (getfield(L, "minSeqNumber", &value) == 0) {
        options.MinSeqNumber = (uint32_t)value;
    }
    if (getfield(L, "topOverCostCount", &value) == 0) {
        options.TopOverCostCount = (uint32_t)value;
    }
    lua_pop(L, 1);
    SetOptions(options);
    return 0;
}

/**
 * 生成唯一id
 * @function idgen.nextid
 * @return uuid uint64 分布式唯一ID
 */
static int
lnextid(lua_State *L) {
    int64_t id = NextId();
	lua_pushinteger(L, id);
    return 1;
}


int
luaopen_idgen(lua_State *L) {
    luaL_Reg l[] = {
        {"set_option",lsetOption},
        {"nextid",lnextid},
        {NULL, NULL}
    };

    luaL_newlib(L,l);
    return 1;
}
